feat(mcp): serve HTML landing page on browser GET to MCP endpoint#1072
Conversation
Co-Authored-By: AJ Steers <aj@airbyte.io>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
👋 Greetings, Airbyte Team Member!Here are some helpful tips and reminders for your convenience. 💡 Show Tips and TricksTesting This PyAirbyte VersionYou can test this version of PyAirbyte using the following: # Run PyAirbyte CLI from this branch:
uvx --from 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1783972828-mcp-browser-landing-page' pyairbyte --help
# Install PyAirbyte from this branch for development:
pip install 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1783972828-mcp-browser-landing-page'PR Slash CommandsAirbyte Maintainers can execute the following slash commands on your PR:
📚 Show Repo GuidanceHelpful ResourcesCommunity SupportQuestions? Join the #pyairbyte channel in our Slack workspace. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a browser-friendly landing page to the computed MCP HTTP mount path, resolves the server URL with a localhost fallback, and raises the minimum ChangesMCP landing page
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant MCPServer
participant http_main.py
participant fastmcp_extensions
MCPServer->>http_main.py: Start main()
http_main.py->>http_main.py: Resolve server URL and MCP path
http_main.py->>fastmcp_extensions: Register GET landing page
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
airbyte/mcp/http_main.py (1)
101-107: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract the
MCP_SERVER_URLlookup into a shared helper?The
os.getenv(MCP_SERVER_URL_ENV, ...)block at lines 103-106 duplicates the same logic inmain()at lines 117-120. If the default URL format ever changes, both spots need updating. Would it make sense to extract a small helper like_get_server_url()and use it in both places? wdyt?♻️ Proposed refactor
+def _get_server_url() -> str: + return os.getenv( + MCP_SERVER_URL_ENV, + f"http://localhost:{DEFAULT_HTTP_PORT}", + ) + async def mcp_landing_page(request: Request) -> HTMLResponse: # noqa: ARG001, RUF029 """Serve a human-friendly landing page for browser `GET`s to the MCP endpoint.""" - server_url = os.getenv( - MCP_SERVER_URL_ENV, - f"http://localhost:{DEFAULT_HTTP_PORT}", - ) + server_url = _get_server_url() return HTMLResponse(_render_mcp_landing_html(server_url, MCP_LANDING_DOCS_URL))And in
main():def main() -> None: """Start the Airbyte MCP server with HTTP transport.""" logging.basicConfig(level=logging.INFO) - server_url = os.getenv( - MCP_SERVER_URL_ENV, - f"http://localhost:{DEFAULT_HTTP_PORT}", - ) + server_url = _get_server_url() mcp_path = "/" if urlparse(server_url).path.strip("/") else "/mcp"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@airbyte/mcp/http_main.py` around lines 101 - 107, Extract the duplicated MCP_SERVER_URL_ENV lookup and default URL construction into a shared helper such as _get_server_url(), then replace the inline logic in both mcp_landing_page and main with that helper. Preserve the existing environment-variable and default-value behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@airbyte/mcp/http_main.py`:
- Around line 101-107: Extract the duplicated MCP_SERVER_URL_ENV lookup and
default URL construction into a shared helper such as _get_server_url(), then
replace the inline logic in both mcp_landing_page and main with that helper.
Preserve the existing environment-variable and default-value behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 478eac4f-c128-4e9b-ba43-6c3d8228af9f
📒 Files selected for processing (1)
airbyte/mcp/http_main.py
Co-Authored-By: AJ Steers <aj@airbyte.io>
Code Coverage OverviewLanguages: Python Python / code-coverage/pytest-fastThe overall coverage in the branch is 67%. The coverage in the branch is 65%. Show a code coverage summary of the most impacted files.
Python / code-coverage/pytest-no-credsThe overall coverage in the branch is 67%. The coverage in the branch is 65%. Show a code coverage summary of the most impacted files.
Python / code-coverage/pytestThe overall coverage in the branch is 72%. The coverage in the branch is 71%. Show a code coverage summary of the most impacted files.
Updated |
Co-Authored-By: AJ Steers <aj@airbyte.io>
Co-Authored-By: AJ Steers <aj@airbyte.io>
Co-Authored-By: AJ Steers <aj@airbyte.io>
…_landing_page Co-Authored-By: AJ Steers <aj@airbyte.io>
…alidation Co-Authored-By: AJ Steers <aj@airbyte.io>
Co-Authored-By: AJ Steers <aj@airbyte.io>
There was a problem hiding this comment.
Pull request overview
This PR improves the developer/operator experience for the Airbyte Cloud MCP endpoint by serving a human-readable HTML landing page when the MCP endpoint is accessed via a browser GET, while keeping MCP POST/DELETE behavior (and OIDC) unchanged.
Changes:
- Bumps
fastmcp-extensionsto>=0.9.0,<1.0.0to use the sharedregister_landing_pagehelper. - Wires
register_landing_page()intoairbyte/mcp/http_main.pyand computes the correct advertised MCP endpoint URL based on mount path. - Updates
uv.lockto resolvefastmcp-extensions==0.9.0and its dependency set.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
uv.lock |
Updates the resolved fastmcp-extensions version to 0.9.0 and reflects its dependency metadata. |
pyproject.toml |
Raises the fastmcp-extensions minimum version to 0.9.0 to ensure register_landing_page is available. |
airbyte/mcp/http_main.py |
Registers a GET-only landing page at the MCP mount path and centralizes server URL retrieval for endpoint computation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-Authored-By: AJ Steers <aj@airbyte.io>
5ba44a2
into
main
Summary
A browser
GETto the Cloud MCP endpoint (https://mcp.internal.airbyte.ai/cloud-mcp) previously returned a bare405 Method Not Allowed. This serves a human-readable landing page instead ("this is an MCP endpoint, add it to your client" + the endpoint URL + a docs link), without touching MCPPOST/DELETEor OIDC.The landing-page HTML + route wiring live upstream in
fastmcp-extensions;http_main.pyjust calls the shared helper:This deletes the local
_render_mcp_landing_html/mcp_landing_pagecopy (~60 lines) and drops the now-unusedhtml/HTMLResponse/Requestimports. In stateless streamable-HTTP mode FastMCP binds onlyPOST/DELETEtomcp_path, so the same-pathGETroute serves browsers without intercepting MCP traffic.register_landing_pageshipped infastmcp-extensions(airbytehq/fastmcp-extensions#65, released as0.9.0). The dependency is pinned tofastmcp-extensions>=0.9.0,<1.0.0anduv.lockresolves the stable0.9.0.Test plan
import airbyte.mcp.http_mainsucceeds and exposesmain;ruff check/ruff format --checkclean.curl -i https://mcp.internal.airbyte.ai/cloud-mcp→200 text/html; unauthenticatedPOST→401.Link to Devin session: https://app.devin.ai/sessions/5bfc7d5ac9544cf1be05a9b1631cc890
Requested by: Aaron ("AJ") Steers (@aaronsteers)
Important
Auto-merge enabled.
This PR is set to merge automatically when all requirements are met.
Note
Auto-merge may have been disabled. Please check the PR status to confirm.